using System;
using System.IO;
using System.Threading;
using XTCast.Mp3;
using System.Collections;

namespace XTCast.Radio {
	
	
	/// <summary>The FileDJ thread reads MP3 files selected by its MusicDirector
	/// and puts the contents into Buffers that can be streamed by Transmitters.
	/// </summary>
	/// 
	public class FileDJ:DJ {

		public FileDJ(Station station, BufferManager bm, StationConfig sc):base(station,bm,sc) {
			this.library = new MediaLibrary(station,sc);
			this.iterator = library;
		}

		protected void HookUpFilters(string filterTypeNames) {
			if (filterTypeNames != null) {
				foreach (String filterTypeName in filterTypeNames.Split(',',';')) {
					IMediaFilter filter = (IMediaFilter) System.Activator.CreateInstance(System.Type.GetType("XTCast.Radio." + filterTypeName), new object[]{station,StationConfig});
					if (filter != null) {
						filter.Start(library, iterator);
						iterator = (IMediaIterator)filter;
					}
				}
			}
		}
		
		protected internal void SpinSilence() {
			while(!SkipTrack && iterator.PeekNextTrack()==null && station.Run) {
				SilenceDJ.PlaySilence();
				Thread.Sleep(500);
			}
			bm.FlushBuffers();
		}

		public override void Skip(TimeSpan ts) {
			ts-=bm.FlushBuffers(ts);
			currentTrack.Position+=ts;
		}

		public override TimeSpan Position {
			get { return currentTrack.Position; }
			set {
				bm.FlushBuffers();
				currentTrack.Position=value;
			}
		}
		
		protected internal void SpinTrack(Track track) {
			try {
				if (track == null) return;
				int bitRate = track.BitRate;
				LOG(1, "Now playing \"" + track.Title + "\" by " + track.Artist + " (\"" + track.Name + "\", " + (bitRate / 1000) + "kbps)");
				track.Open(StationConfig.Format.Channels,StationConfig.Format.SampleRate,StationConfig.Format.Bitrate,StationConfig.Format.MaxBitrate);
				try {
					while (true) {
						if (!station.Run) return;
						if (SkipTrack) {
							bm.FlushBuffers();
							return;
						}
						if (bm.Fill) {
							Buffer[] buf = bm.LoadBuffers(track, track, Math.Max(1,bm.NumToFill()));
							if (buf == null) return;
							bm.Add(buf);
						} else Thread.Sleep(1000);
						Track nextTrack = iterator.PeekNextTrack();
						if (nextTrack!=null)
							nextTrack.PreBuffer(StationConfig.Format.Channels,StationConfig.Format.SampleRate);
					}
				}
				finally {
					track.Close();
				}
			}
			catch(ThreadAbortException x) {
				throw x;
			}
			catch (Exception x) {
				Station.OnTrackError(track);
				Log.Error(this,x);
			}
		}
		
		Track currentTrack;
		public void  Run() {
			Log.Info(this,"Starting...");
			library.Start();
			HookUpFilters("PlaylistFilter");
			try {
				while (station.Run) {
					 currentTrack = iterator.GetNextTrack();
					if (currentTrack!=null)
						SpinTrack(currentTrack);
					else
						SpinSilence();
				}
			} catch (System.Threading.ThreadInterruptedException ix) {
				throw ix;
			} catch (Exception ex) {
				Log.Error(this,ex);
			}
			Log.Info(this,"Stopping...");
		}

		virtual public FileDJConfig Config {
			get {
				return StationConfig.FileDJ;
			}
		}
		
		// INSTANCE DATA:
		
		private IMediaIterator iterator;
		private Throttle throttle;
		private Thread thread;
		private IMediaLibrary library;
	
		public override void Start() {
			thread = new Thread(new ThreadStart(Run));
			thread.Name = ToString();
			thread.IsBackground=true;
			thread.Priority = ThreadPriority.Normal;
			thread.Start();
		}
	}
}